const main = {
  /**
   * 渲染块
   * @param {Object} params
   */
  drawBlock({
    text,
    width = 0,
    height,
    x,
    y,
    paddingLeft = 0,
    paddingRight = 0,
    borderWidth,
    backgroundColor,
    borderColor,
    borderRadius,
    opacity = 1
  }) {
    // 判断是否块内有文字
    let blockWidth = 0; // 块的宽度
    let textX = 0;
    let textY = 0;
    if (typeof text !== 'undefined') {
      // 如果有文字并且块的宽度小于文字宽度，块的宽度为 文字的宽度 + 内边距
      const textWidth = this._getTextWidth(typeof text.text === 'string' ? text : text.text);
      blockWidth = textWidth > width ? textWidth : width;
      blockWidth += paddingLeft + paddingLeft;

      const {
        textAlign = 'left', text: textCon
      } = text;
      textY = height / 2 + y; // 文字的y轴坐标在块中线
      if (textAlign === 'left') {
        // 如果是右对齐，那x轴在块的最左边
        textX = x + paddingLeft;
      } else if (textAlign === 'center') {
        textX = blockWidth / 2 + x;
      } else {
        textX = x + blockWidth - paddingRight;
      }
    } else {
      blockWidth = width;
    }

    if (backgroundColor) {
      // 画面
      this.ctx.save();
      this.ctx.setGlobalAlpha(opacity);
      this.ctx.setFillStyle(backgroundColor);
      if (borderRadius > 0) {
        // 画圆角矩形
        this._drawRadiusRect(x, y, blockWidth, height, borderRadius);
        this.ctx.fill();
      } else {
        this.ctx.fillRect(this.toPx(x), this.toPx(y), this.toPx(blockWidth), this.toPx(height));
      }
      this.ctx.restore();
    }
    if (borderWidth) {
      // 画线
      this.ctx.save();
      this.ctx.setGlobalAlpha(opacity);
      this.ctx.setStrokeStyle(borderColor);
      this.ctx.setLineWidth(this.toPx(borderWidth));
      if (borderRadius > 0) {
        // 画圆角矩形边框
        this._drawRadiusRect(x, y, blockWidth, height, borderRadius);
        this.ctx.stroke();
      } else {
        this.ctx.strokeRect(this.toPx(x), this.toPx(y), this.toPx(blockWidth), this.toPx(height));
      }
      this.ctx.restore();
    }

    if (text) {
      this.drawText(Object.assign(text, {
        x: textX,
        y: textY
      }))
    }
  },

  /**
   * 渲染文字
   * @param {Object} params
   */
  drawText(params) {
    const {
      x,
      y,
      fontSize,
      color,
      baseLine,
      textAlign,
      text,
      opacity = 1,
      width,
      lineNum,
      lineHeight
    } = params;
    if (Object.prototype.toString.call(text) === '[object Array]') {
      let preText = {
        x,
        y,
        baseLine
      };
      text.forEach(item => {
        preText.x += item.marginLeft || 0;
        const textWidth = this._drawSingleText(Object.assign(item, {
          ...preText,
        }));
        preText.x += textWidth + (item.marginRight || 0); // 下一段字的x轴为上一段字x + 上一段字宽度
      })
    } else {
     if(params.yihang){
       this._drawOneHangText(params);
     }else{
       this._drawSingleText(params);
     }
      
    }
  },
  /**
   * 渲染图片
   */
  drawImage(data) {
    const {
      imgPath,
      x,
      y,
      w,
      h,
      sx,
      sy,
      sw,
      sh,
      borderRadius = 0,
      borderWidth = 0,
      borderColor
    } = data;
    if (imgPath) {
      this.ctx.save();
      if (borderRadius > 0) {
        this._drawRadiusRect(x, y, w, h, borderRadius);
        this.ctx.strokeStyle = 'rgba(255,255,255,0)';
        this.ctx.stroke();
        this.ctx.clip();
        this.ctx.drawImage(imgPath, this.toPx(sx), this.toPx(sy), this.toPx(sw), this.toPx(sh), this.toPx(x), this.toPx(y), this.toPx(w), this.toPx(h));
        if (borderWidth > 0) {
          this.ctx.setStrokeStyle(borderColor);
          this.ctx.setLineWidth(this.toPx(borderWidth));
          this.ctx.stroke();
        }
      } else {
        this.ctx.drawImage(imgPath, this.toPx(sx), this.toPx(sy), this.toPx(sw), this.toPx(sh), this.toPx(x), this.toPx(y), this.toPx(w), this.toPx(h));
      }
      this.ctx.restore();      
    }
  },
  /**
   * 渲染线
   * @param {*} param0
   */
  drawLine({
    startX,
    startY,
    endX,
    endY,
    color,
    width
  }) {
    this.ctx.save();
    this.ctx.beginPath();
    this.ctx.setStrokeStyle(color);
    this.ctx.setLineWidth(this.toPx(width));
    this.ctx.moveTo(this.toPx(startX), this.toPx(startY));
    this.ctx.lineTo(this.toPx(endX), this.toPx(endY));
    this.ctx.stroke();
    this.ctx.closePath();
    this.ctx.restore();
  },
  downloadResource(images = []) {
    const drawList = [];
    this.drawArr = [];
    images.forEach((image, index) => { //过滤掉图片url为空的情况
      if (image.url) {
        drawList.push(this._downloadImageAndInfo(image, index))
      }
    });
    return Promise.all(drawList);
  },
  initCanvas(w, h, debug) {
    return new Promise((resolve) => {
      this.setData({
        pxWidth: this.toPx(w),
        pxHeight: this.toPx(h),
        debug,
      }, resolve);
    });
  }
}
const handle = {
  /**
   * 画圆角矩形
   */
  _drawRadiusRect(x, y, w, h, r) {
    const br = r / 2;
    this.ctx.beginPath();
    this.ctx.moveTo(this.toPx(x + br), this.toPx(y)); // 移动到左上角的点
    this.ctx.lineTo(this.toPx(x + w - br), this.toPx(y));
    this.ctx.arc(this.toPx(x + w - br), this.toPx(y + br), this.toPx(br), 2 * Math.PI * (3 / 4), 2 * Math.PI * (4 / 4))
    this.ctx.lineTo(this.toPx(x + w), this.toPx(y + h - br));
    this.ctx.arc(this.toPx(x + w - br), this.toPx(y + h - br), this.toPx(br), 0, 2 * Math.PI * (1 / 4))
    this.ctx.lineTo(this.toPx(x + br), this.toPx(y + h));
    this.ctx.arc(this.toPx(x + br), this.toPx(y + h - br), this.toPx(br), 2 * Math.PI * (1 / 4), 2 * Math.PI * (2 / 4))
    this.ctx.lineTo(this.toPx(x), this.toPx(y + br));
    this.ctx.arc(this.toPx(x + br), this.toPx(y + br), this.toPx(br), 2 * Math.PI * (2 / 4), 2 * Math.PI * (3 / 4))
  },
  /**
   * 计算文本长度
   * @param {Array|Object}} text 数组 或者 对象
   */
  _getTextWidth(text) {
    let texts = [];
    if (Object.prototype.toString.call(text) === '[object Object]') {
      texts.push(text);
    } else {
      texts = text;
    }
    let width = 0;
    texts.forEach(({
      fontSize,
      text,
      marginLeft = 0,
      marginRight = 0
    }) => {
      this.ctx.setFontSize(this.toPx(fontSize));
      width += this.ctx.measureText(text).width + marginLeft + marginRight;
    })

    return this.toRpx(width);
  },
  /**
   * 渲染一段文字
   */
  _drawSingleText({
    x,
    y,
    fontSize,
    color,
    baseLine,
    textAlign = 'left',
    text,
    opacity = 1,
    textDecoration = 'none',
    width,
    lineNum = 2,
    lineHeight = 40,
    fontWeight = 'normal',
    fontStyle = 'normal',
    fontFamily = "sans-serif"
  }) {
    this.ctx.save();
    this.ctx.beginPath();
    this.ctx.font = fontStyle + " " + fontWeight + " " + this.toPx(fontSize, true) + "px " + fontFamily
    this.ctx.setGlobalAlpha(opacity);
    // this.ctx.setFontSize(this.toPx(fontSize));
    this.ctx.setFillStyle(color);
    this.ctx.setTextBaseline(baseLine);
    this.ctx.setTextAlign(textAlign);
    let textWidth = this.toRpx(this.ctx.measureText(text).width);
    const textArr = [];
    if (textWidth > width) {
      // 文本宽度 大于 渲染宽度
      let fillText = '';
      let line = 1;
      for (let i = 0; i <= text.length - 1; i++) { // 将文字转为数组，一行文字一个元素
        fillText = fillText + text[i];
        let huanhangFlag = text[i].indexOf("\n") >= 0?true:false
        if(huanhangFlag){//处理换行标记
          if (line <lineNum) {
            textArr.push(fillText);
          }
          if (line ==lineNum) {
            textArr.push(fillText.substring(0, fillText.length - 1) + '...');
          }
          fillText = '';
          line++;
        }else if (this.toRpx(this.ctx.measureText(fillText).width) >= width) {
          if (line === lineNum) {
            if (i !== text.length - 1) {
              fillText = fillText.substring(0, fillText.length - 1) + '...';
            }
          }
          if (line <= lineNum) {
            textArr.push(fillText);
          }
          fillText = '';
          line++;
        } else {
          if (line <= lineNum) {
            if (i === text.length - 1) {
              textArr.push(fillText);
            }
          }
        }
      }
      textWidth = width;
    } else {
      textArr.push(text);
    }

    textArr.forEach((item, index) => {
      this.ctx.fillText(item, this.toPx(x), this.toPx(y + (lineHeight || fontSize) * index));
    })

    this.ctx.restore();

    // textDecoration
    if (textDecoration !== 'none') {
      let lineY = y;
      if (textDecoration === 'line-through') {
        // 目前只支持贯穿线
        lineY = y;
      }
      this.ctx.save();
      this.ctx.moveTo(this.toPx(x), this.toPx(lineY));
      this.ctx.lineTo(this.toPx(x) + this.toPx(textWidth), this.toPx(lineY));
      this.ctx.setStrokeStyle(color);
      this.ctx.stroke();
      this.ctx.restore();
    }

    return textWidth;
  },


  _drawOneHangText({
    x,
    y,
    fontSize,
    color,
    baseLine,
    textAlign = 'left',
    text,
    opacity = 1,
    textDecoration = 'none',
    width,
    lineNum = 1,
    lineHeight = 0,
    fontWeight = 'normal',
    fontStyle = 'normal',
    fontFamily = "sans-serif"
  }) {
    this.ctx.save();
    this.ctx.beginPath();
    this.ctx.font = fontStyle + " " + fontWeight + " " + this.toPx(fontSize, true) + "px " + fontFamily
    this.ctx.setGlobalAlpha(opacity);
    // this.ctx.setFontSize(this.toPx(fontSize));
    this.ctx.setFillStyle(color);
    this.ctx.setTextBaseline(baseLine);
    this.ctx.setTextAlign(textAlign);
    let textWidth = this.toRpx(this.ctx.measureText(text).width);
    const textArr = [];
    if (textWidth > width) {
      // 文本宽度 大于 渲染宽度
      let fillText = '';
      let line = 1;
      for (let i = 0; i <= text.length - 1; i++) { // 将文字转为数组，一行文字一个元素
        fillText = fillText + text[i];
        if (this.toRpx(this.ctx.measureText(fillText).width) >= width) {
          if (line === lineNum) {
            if (i !== text.length - 1) {
              fillText = fillText.substring(0, fillText.length - 1) + '...';
            }
          }
          if (line <= lineNum) {
            textArr.push(fillText);
          }
          fillText = '';
          line++;
        } else {
          if (line <= lineNum) {
            if (i === text.length - 1) {
              textArr.push(fillText);
            }
          }
        }
      }
      textWidth = width;
    } else {
      textArr.push(text);
    }

    textArr.forEach((item, index) => {
      this.ctx.fillText(item, this.toPx(x), this.toPx(y + (lineHeight || fontSize) * index));
    })

    this.ctx.restore();

    // textDecoration
    if (textDecoration !== 'none') {
      let lineY = y;
      if (textDecoration === 'line-through') {
        // 目前只支持贯穿线
        lineY = y;
      }
      this.ctx.save();
      this.ctx.moveTo(this.toPx(x), this.toPx(lineY));
      this.ctx.lineTo(this.toPx(x) + this.toPx(textWidth), this.toPx(lineY));
      this.ctx.setStrokeStyle(color);
      this.ctx.stroke();
      this.ctx.restore();
    }

    return textWidth;
  },
}
const helper = {
  /**
   * 下载图片并获取图片信息
   */
  _downloadImageAndInfo(image, index) {
    return new Promise((resolve, reject) => {
      const {
        x,
        y,
        url,
        zIndex
      } = image;
      const imageUrl = url;
      // 下载图片
      this._downImage(imageUrl, index)
        // 获取图片信息
        .then(imgPath => this._getImageInfo(imgPath, index))
        .then(({
          imgPath,
          imgInfo
        }) => {
          // 根据画布的宽高计算出图片绘制的大小，这里会保证图片绘制不变形
          let sx;
          let sy;
          const borderRadius = image.borderRadius || 0;
          const setWidth = image.width;
          const setHeight = image.height;
          const width = this.toRpx(imgInfo.width);
          const height = this.toRpx(imgInfo.height);

          if (width / height <= setWidth / setHeight) {
            sx = 0;
            sy = (height - ((width / setWidth) * setHeight)) / 2;
          } else {
            sy = 0;
            sx = (width - ((height / setHeight) * setWidth)) / 2;
          }
          this.drawArr.push({
            type: 'image',
            borderRadius,
            borderWidth: image.borderWidth,
            borderColor: image.borderColor,
            zIndex: typeof zIndex !== 'undefined' ? zIndex : index,
            imgPath,
            sx,
            sy,
            sw: (width - (sx * 2)),
            sh: (height - (sy * 2)),
            x,
            y,
            w: setWidth,
            h: setHeight,
          });
          resolve();
        })
        .catch(err => reject(err));
    });
  },
  /**
   * 下载图片资源
   * @param {*} imageUrl
   */
  _downImage(imageUrl) {
    return new Promise((resolve, reject) => {
      if (/^http/.test(imageUrl) && !new RegExp(wx.env.USER_DATA_PATH).test(imageUrl)) {
        wx.downloadFile({
          url: this._mapHttpToHttps(imageUrl),
          success: (res) => {
            if (res.statusCode === 200) {
              resolve(res.tempFilePath);
            } else {
              reject(res.errMsg);
            }
          },
          fail(err) {
            reject(err);
          },
        });
      } else {
        // 支持本地地址
        resolve(imageUrl);
      }
    });
  },
  /**
   * 获取图片信息
   * @param {*} imgPath
   * @param {*} index
   */
  _getImageInfo(imgPath, index) {
    return new Promise((resolve, reject) => {
      wx.getImageInfo({
        src: imgPath,
        success(res) {
          resolve({
            imgPath,
            imgInfo: res,
            index
          });
        },
        fail(err) {
          reject(err);
        },
      });
    });
  },
  toPx(rpx, int) {
    if (int) {
      return parseInt(rpx * this.factor);
    }
    return rpx * this.factor;
  },
  toRpx(px, int) {
    if (int) {
      return parseInt(px / this.factor);
    }
    return px / this.factor;
  },
  /**
   * 将http转为https
   * @param {String}} rawUrl 图片资源url
   */
  _mapHttpToHttps(rawUrl) {
    if (rawUrl.indexOf(':') < 0) {
      return rawUrl;
    }
    const urlComponent = rawUrl.split(':');
    if (urlComponent.length === 2) {
      if (urlComponent[0] === 'http') {
        urlComponent[0] = 'https';
        return `${urlComponent[0]}:${urlComponent[1]}`;
      }
    }
    return rawUrl;
  },
}
Component({
  properties: {},
  created() {
    const sysInfo = wx.getSystemInfoSync();
    const screenWidth = sysInfo.screenWidth;
    this.factor = screenWidth / 750;
  },
  methods: Object.assign({
    /**
     * 计算画布的高度
     * @param {*} config
     */
    getHeight(config) {
      const getTextHeight = (text) => {
        let fontHeight = text.lineHeight || text.fontSize;
        let height = 0;
        if (text.baseLine === 'top') {
          height = fontHeight;
        } else if (text.baseLine === 'middle') {
          height = fontHeight / 2;
        } else {
          height = 0;
        }
        return height;
      }
      const heightArr = [];
      (config.blocks || []).forEach((item) => {
        heightArr.push(item.y + item.height);
      });
      (config.texts || []).forEach((item) => {
        let height;
        if (Object.prototype.toString.call(item.text) === '[object Array]') {
          item.text.forEach((i) => {
            height = getTextHeight({ ...i,
              baseLine: item.baseLine
            });
            heightArr.push(item.y + height);
          });
        } else {
          height = getTextHeight(item);
          heightArr.push(item.y + height);
        }
      });
      (config.images || []).forEach((item) => {
        heightArr.push(item.y + item.height);
      });
      (config.lines || []).forEach((item) => {
        heightArr.push(item.startY);
        heightArr.push(item.endY);
      });
      const sortRes = heightArr.sort((a, b) => b - a);
      let canvasHeight = 0;
      if (sortRes.length > 0) {
        canvasHeight = sortRes[0];
      }
      if (config.height < canvasHeight || !config.height) {
        return canvasHeight;
      } else {
        return config.height;
      }
    },
    create(config) {
      this.ctx = wx.createCanvasContext('canvasid', this);

      const height = this.getHeight(config);
      this.initCanvas(config.width, height, config.debug)
        .then(() => {
          // 设置画布底色
          if (config.backgroundColor) {
            this.ctx.save();
            this.ctx.setFillStyle(config.backgroundColor);
            this._drawRadiusRect(0, 0, config.width, height, config.borderRadius);
            this.ctx.fill();
          }
          // if (config.borderColor) {
          //   this.ctx.save();
          //   this.ctx.setGlobalAlpha(config.opacity);                    
          //   this.ctx.setStrokeStyle(config.borderColor);
          //   this.ctx.setLineWidth(this.toPx(config.borderWidth));
          //   if (config.borderRadius > 0) {
          //     this._drawRadiusRect(0, 0, config.width, height, config.borderRadius);
          //     this.ctx.stroke();
          //   } else {
          //     this.ctx.strokeRect(0, 0, config.width, height);
          //   }
          //   this.ctx.restore();                  


          // }
          const {
            texts = [], images = [], blocks = [], lines = []
          } = config;
          const queue = this.drawArr
            .concat(texts.map((item) => {
              item.type = 'text';
              item.zIndex = item.zIndex || 0;
              return item;
            }))
            .concat(blocks.map((item) => {
              item.type = 'block';
              item.zIndex = item.zIndex || 0;
              return item;
            }))
            .concat(lines.map((item) => {
              item.type = 'line';
              item.zIndex = item.zIndex || 0;
              return item;
            }));
          // 按照顺序排序
          queue.sort((a, b) => a.zIndex - b.zIndex);

          queue.forEach((item) => {
            if (item.type === 'image') {
              this.drawImage(item)
            } else if (item.type === 'text') {
              this.drawText(item)
            } else if (item.type === 'block') {
              this.drawBlock(item)
            } else if (item.type === 'line') {
              this.drawLine(item)
            }
          });

          const res = wx.getSystemInfoSync();
          const platform = res.platform;
          let time = 0;
          if (platform === 'android') {
            // 在安卓平台，经测试发现如果海报过于复杂在转换时需要做延时，要不然样式会错乱
            time = 300;
          }
          this.ctx.draw(false, () => {
            setTimeout(() => {
              wx.canvasToTempFilePath({
                canvasId: 'canvasid',
                success: (res) => {
                  this.triggerEvent('success', res.tempFilePath);
                },
                fail: (err) => {
                  this.triggerEvent('fail', err);
                },
              }, this);
            }, time);
          });
        })
        .catch((err) => {
          wx.showToast({
            icon: 'none',
            title: err.errMsg || '生成失败'
          });
          console.error(err);
        });
    },
  }, main, handle, helper),
});